2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #ifndef __JUCER_PAINTELEMENTIMAGE_JUCEHEADER__
27 #define __JUCER_PAINTELEMENTIMAGE_JUCEHEADER__
29 #include "../jucer_PaintRoutine.h"
30 #include "../../properties/jucer_FilePropertyComponent.h"
31 #include "jucer_ImageResourceProperty.h"
32 #include "jucer_PaintElementUndoableAction.h"
35 //==============================================================================
38 class PaintElementImage
: public PaintElement
45 proportionalReducingOnly
= 2
48 //==============================================================================
49 PaintElementImage (PaintRoutine
* owner
)
50 : PaintElement (owner
, "Image"),
60 //==============================================================================
61 const Drawable
* getDrawable()
63 JucerDocument
* const document
= getDocument();
66 return document
->getResources().getDrawable (resourceName
);
71 void draw (Graphics
& g
, const ComponentLayout
* layout
, const Rectangle
<int>& parentArea
)
73 const Rectangle
<int> r (position
.getRectangle (parentArea
, layout
));
75 const Drawable
* const image
= getDrawable();
79 image
->drawWithin (g
, r
.toFloat(),
80 mode
== stretched
? RectanglePlacement::stretchToFit
81 : (mode
== proportionalReducingOnly
? (RectanglePlacement::centred
| RectanglePlacement::onlyReduceInSize
)
82 : RectanglePlacement::centred
),
87 g
.setColour (Colours::grey
.withAlpha (0.5f
));
90 g
.setColour (Colours::black
);
91 g
.drawText ("(image missing)",
92 r
.getX(), r
.getY(), r
.getWidth(), r
.getHeight(),
93 Justification::centred
, true);
97 //==============================================================================
98 void getEditableProperties (Array
<PropertyComponent
*>& properties
)
100 PaintElement::getEditableProperties (properties
);
102 properties
.add (new ImageElementResourceProperty (this));
103 properties
.add (new StretchModeProperty (this));
104 properties
.add (new OpacityProperty (this));
105 properties
.add (new ResetSizeProperty (this));
108 void fillInGeneratedCode (GeneratedCode
& code
, String
& paintMethodCode
)
114 if (dynamic_cast <const DrawableImage
*> (getDrawable()) != 0)
116 const String
imageVariable ("cachedImage_" + resourceName
);
118 code
.addImageResourceLoader (imageVariable
, resourceName
);
120 if (opacity
>= 254.0 / 255.0)
121 r
<< "g.setColour (Colours::black);\n";
123 r
<< "g.setColour (Colours::black.withAlpha (" << valueToFloat (opacity
) << "));\n";
126 positionToCode (position
, getDocument()->getComponentLayout(), x
, y
, w
, h
);
128 if (mode
== stretched
)
130 r
<< "g.drawImage (" << imageVariable
<< ",\n "
131 << x
<< ", " << y
<< ", " << w
<< ", " << h
133 << imageVariable
<< ".getWidth(), "
134 << imageVariable
<< ".getHeight());\n\n";
138 r
<< "g.drawImageWithin (" << imageVariable
<< ",\n "
139 << x
<< ", " << y
<< ", " << w
<< ", " << h
142 if (mode
== proportionalReducingOnly
)
143 r
<< "RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize";
145 r
<< "RectanglePlacement::centred";
147 r
<< ",\n false);\n\n";
150 paintMethodCode
+= r
;
154 if (resourceName
.isNotEmpty())
156 const String
imageVariable (L
"drawable" + String (code
.getUniqueSuffix()));
158 code
.privateMemberDeclarations
159 << "Drawable* " << imageVariable
<< ";\n";
162 << imageVariable
<< " = Drawable::createFromImageData ("
163 << resourceName
<< ", " << resourceName
<< "Size);\n";
166 << "deleteAndZero (" << imageVariable
<< ");\n";
168 if (opacity
>= 254.0 / 255.0)
169 r
<< "g.setColour (Colours::black);\n";
171 r
<< "g.setColour (Colours::black.withAlpha (" << valueToFloat (opacity
) << "));\n";
174 positionToCode (position
, code
.document
->getComponentLayout(), x
, y
, w
, h
);
176 r
<< "jassert (" << imageVariable
<< " != 0);\n"
177 << "if (" << imageVariable
<< " != 0)\n "
178 << imageVariable
<< "->drawWithin (g, "
179 << x
<< ", " << y
<< ", " << w
<< ", " << h
181 << String::repeatedString (" ", imageVariable
.length() + 18)
182 << (mode
== stretched
? "RectanglePlacement::stretchToFit"
183 : (mode
== proportionalReducingOnly
? "RectanglePlacement::centred | RectanglePlacement::onlyReduceInSize"
184 : "RectanglePlacement::centred"))
185 << ", " << valueToFloat (opacity
)
188 paintMethodCode
+= r
;
192 jassertfalse
// this resource isn't valid!
198 //==============================================================================
199 class SetResourceAction
: public PaintElementUndoableAction
<PaintElementImage
>
202 SetResourceAction (PaintElementImage
* const element
, const String
& newResource_
)
203 : PaintElementUndoableAction
<PaintElementImage
> (element
),
204 newResource (newResource_
)
206 oldResource
= element
->getResource();
212 getElement()->setResource (newResource
, false);
219 getElement()->setResource (oldResource
, false);
224 String newResource
, oldResource
;
227 void setResource (const String
& newName
, const bool undoable
)
229 if (resourceName
!= newName
)
233 perform (new SetResourceAction (this, newName
),
234 "Change image resource");
238 resourceName
= newName
;
246 const String
getResource() const
251 //==============================================================================
252 class SetOpacityAction
: public PaintElementUndoableAction
<PaintElementImage
>
255 SetOpacityAction (PaintElementImage
* const element
, const double newOpacity_
)
256 : PaintElementUndoableAction
<PaintElementImage
> (element
),
257 newOpacity (newOpacity_
)
259 oldOpacity
= element
->getOpacity();
265 getElement()->setOpacity (newOpacity
, false);
272 getElement()->setOpacity (oldOpacity
, false);
277 double newOpacity
, oldOpacity
;
280 void setOpacity (double newOpacity
, const bool undoable
)
282 newOpacity
= jlimit (0.0, 1.0, newOpacity
);
284 if (opacity
!= newOpacity
)
288 perform (new SetOpacityAction (this, newOpacity
),
289 "Change image opacity");
293 opacity
= newOpacity
;
299 double getOpacity() const throw() { return opacity
; }
301 //==============================================================================
302 static const char* getTagName() throw() { return "IMAGE"; }
304 void resetToImageSize()
306 const Drawable
* const image
= getDrawable();
308 if (image
!= 0 && getParentComponent() != 0)
310 const Rectangle
<int> parentArea (((PaintRoutineEditor
*) getParentComponent())->getComponentArea());
312 Rectangle
<int> r (getCurrentBounds (parentArea
));
313 Rectangle
<float> bounds (image
->getDrawableBounds());
315 r
.setSize ((int) (bounds
.getWidth() + 0.999f
), (int) (bounds
.getHeight() + 0.999f
));
317 setCurrentBounds (r
, parentArea
, true);
321 //==============================================================================
322 class SetStretchModeAction
: public PaintElementUndoableAction
<PaintElementImage
>
325 SetStretchModeAction (PaintElementImage
* const element
, const StretchMode newValue_
)
326 : PaintElementUndoableAction
<PaintElementImage
> (element
),
329 oldValue
= element
->getStretchMode();
335 getElement()->setStretchMode (newValue
, false);
342 getElement()->setStretchMode (oldValue
, false);
347 StretchMode newValue
, oldValue
;
350 StretchMode
getStretchMode() const throw() { return mode
; }
352 void setStretchMode (const StretchMode newMode
, const bool undoable
)
358 perform (new SetStretchModeAction (this, newMode
),
359 "Change image mode");
369 //==============================================================================
370 XmlElement
* createXml() const
372 XmlElement
* e
= new XmlElement (getTagName());
373 position
.applyToXml (*e
);
374 e
->setAttribute ("resource", resourceName
);
375 e
->setAttribute ("opacity", opacity
);
376 e
->setAttribute ("mode", (int) mode
);
381 bool loadFromXml (const XmlElement
& xml
)
383 if (xml
.hasTagName (getTagName()))
385 position
.restoreFromXml (xml
, position
);
386 resourceName
= xml
.getStringAttribute ("resource", String::empty
);
387 opacity
= xml
.getDoubleAttribute ("opacity", 1.0);
388 mode
= (StretchMode
) xml
.getIntAttribute ("mode", (int) stretched
);
405 //==============================================================================
406 class ImageElementResourceProperty
: public ImageResourceProperty
<PaintElementImage
>
409 ImageElementResourceProperty (PaintElementImage
* const element_
)
410 : ImageResourceProperty
<PaintElementImage
> (element_
, "image source")
414 //==============================================================================
415 void setResource (const String
& newName
)
417 element
->setResource (newName
, true);
420 const String
getResource() const
422 return element
->getResource();
426 //==============================================================================
427 class OpacityProperty
: public SliderPropertyComponent
,
428 private ChangeListener
431 OpacityProperty (PaintElementImage
* const element_
)
432 : SliderPropertyComponent ("opacity", 0.0, 1.0, 0.001),
435 element
->getDocument()->addChangeListener (this);
440 element
->getDocument()->removeChangeListener (this);
443 void setValue (double newValue
)
445 element
->getDocument()->getUndoManager().undoCurrentTransactionOnly();
447 element
->setOpacity (newValue
, true);
450 double getValue() const
452 return element
->getOpacity();
455 void changeListenerCallback (ChangeBroadcaster
*)
461 PaintElementImage
* const element
;
464 class StretchModeProperty
: public ChoicePropertyComponent
,
465 private ChangeListener
468 StretchModeProperty (PaintElementImage
* const element_
)
469 : ChoicePropertyComponent ("stretch mode"),
472 choices
.add ("Stretched to fit");
473 choices
.add ("Maintain aspect ratio");
474 choices
.add ("Maintain aspect ratio, only reduce in size");
476 element
->getDocument()->addChangeListener (this);
479 ~StretchModeProperty()
481 element
->getDocument()->removeChangeListener (this);
484 void setIndex (int newIndex
)
486 element
->setStretchMode ((StretchMode
) newIndex
, true);
491 return (int) element
->getStretchMode();
494 void changeListenerCallback (ChangeBroadcaster
*)
500 PaintElementImage
* const element
;
503 class ResetSizeProperty
: public ButtonPropertyComponent
506 ResetSizeProperty (PaintElementImage
* const element_
)
507 : ButtonPropertyComponent ("reset", false),
514 element
->resetToImageSize();
517 const String
getButtonText() const { return "reset to image size"; }
520 PaintElementImage
* const element
;
525 #endif // __JUCER_PAINTELEMENTIMAGE_JUCEHEADER__